package database

import (
	"blog/util"

	"gorm.io/gorm"
)

type User struct { //默认情况下，驼峰对应的蛇形复数(users)即为数据库里的表名
	Id     int    `gorm:"column:id;primaryKey"` //默认情况下，id为主键
	Name   string `gorm:"column:name"`          //默认情况下，驼峰对应的蛇形即为数据库里的列名。name
	PassWd string `gorm:"column:password"`      //pass_wd
}

func (User) TableName() string { //显示指定表名
	return "user"
}

var (
	_all_user_field = util.GetGormFields(User{})
)

// 根据用户名检索用户
func GetUserByName(name string) *User {
	db := GetBlogDBConnection()
	var user User
	if err := db.Select(_all_user_field).Where("name=?", name).First(&user).Error; err != nil { //name不存在重复，所以用First即可
		if err != gorm.ErrRecordNotFound { // 如果是用户名不存在，不需要打错误日志
			util.LogRus.Errorf("get password of user %s failed: %s", name, err) // 系统性异常，才打错误日志
		}
		return nil
	}
	return &user
}

// 创建一个用户
func CreateUser(name, pass string) {
	db := GetBlogDBConnection()
	pass = util.Md5(pass)                          //密码经过md5
	user := User{Name: name, PassWd: pass}         //ORM
	if err := db.Create(&user).Error; err != nil { //必须传指针，因为要给user的主键赋值
		util.LogRus.Errorf("create user %s failed: %s", name, err)
	} else {
		util.LogRus.Infof("create user id %d", user.Id)
	}
}

// 创建用户（密码已经哈希过）
func CreateUserWithHashedPassword(name, hashedPass string) error {
	db := GetBlogDBConnection()
	user := User{Name: name, PassWd: hashedPass}   // 直接使用已经哈希的密码
	if err := db.Create(&user).Error; err != nil { // 必须传指针，因为要给user的主键赋值
		util.LogRus.Errorf("create user %s failed: %s", name, err)
		return err
	} else {
		util.LogRus.Infof("create user id %d", user.Id)
		return nil
	}
}

// 删除一个用户
func DeleteUser(name string) {
	db := GetBlogDBConnection()
	if err := db.Where("name=?", name).Delete(User{}).Error; err != nil { //Delete操作必须有where条件
		util.LogRus.Errorf("delete user %s failed: %s", name, err)
	}
}

/*
func RegisterUser(name string, password string)( int,error){ //返回用户id是自增的 注册可能失败
	user:=model.User{
		Name:name,
		PassWord:password,
	}
	err:= blog_mysql.Create(&user).Error// Create   必须传入指针会给ID赋值
	 if(err!=nil){
		var mysqlError *mysql.MySQLError
		if errors.As(err, &mysqlError) {//把errors 转到mysqlError里面去
			if mysqlError.Number == 1062 {
				return 0, fmt.Errorf("用户名[%s]已经存在",name)
			}
		}
		slog.Error("用户注册失败","name",name,"error",err)
		return 0, errors.New("用户注册失败,请稍后重试")
	 }
   return user.Id,nil
}

//注销用户
func LogOffUser(uid int) error {
	//这个Id就是where条件
	tx:= blog_mysql.Delete(model.User{Id:uid})


	if tx.Error!=nil{
		slog.Error("注销用户失败","id",uid,"error",tx.Error)
		return errors.New("注销用户失败,请稍后重试")
	}
	if tx.RowsAffected==0{ //删除了0行数据 说明没有这个id
		slog.Error("注销用户失败","id",uid,"error","用户不存在")
		return fmt.Errorf("注销用户失败","id",uid,"error","用户不存在")

	}

	return  nil

}

func UpdatePassword(uid int,oldPassword,newPassword string) error{
	//更新多列用Updates
  tx:=   blog_mysql.Model(&model.User{Id:uid}).Where("id=? and password=?",uid,oldPassword).Update("password",newPassword)
	if tx.Error!=nil{
		slog.Error("更新密码失败","uid",uid,"error",tx.Error)

		return errors.New("用户名修改密码失败， 请稍后重试")
	}else {
		if tx.RowsAffected == 0 {//  没有修改任何一行记录
			slog.Error("更新密码失败","uid",uid,"error","没有修改任何一行记录")
			return errors.New("用户id和旧码不对")

		}
	}

	return nil

}

func GetUserById(uid int) *model.User {
	//id 可能不存在
	user:= model.User{Id: uid}
	tx:= blog_mysql.Select("*").First(&user)
	if tx.Error != nil {
		//不是gorm就打印日志
		if !errors.Is(tx.Error, gorm.ErrRecordNotFound){// 系统级别错误 数据库本身出问题了
			slog.Error("查询用户失败","uid",uid,"error",tx.Error)
			return nil
		}
	 //其他错误
		return nil
	}

	return &user
}


func GetUserByUserName(userName string) *model.User {


	//id 可能不存在
	user:= model.User{}
	tx:= blog_mysql.Select("*").Where("name=?",userName).First(&user)
	if tx.Error != nil {
		//不是gorm就打印日志
		if !errors.Is(tx.Error, gorm.ErrRecordNotFound){// 系统级别错误 数据库本身出问题了
			slog.Error("查询用户失败","userName",userName,"error",tx.Error)
			return nil
		}
	 //其他错误
		return nil
	}

	return &user
}

*/
